﻿/*
 * @Autor: PK
 * @Date: 2021-03-31 16:36:36
 * @Description: 路网实现类CreateInitCustomers() 生成初始顾客,可以查看AbstractNetwork源码选择
 * 重写AfterFactoryCreated、BeforeRoadsCreate、BeforeAgenciesCreate、AfterCustomersCreated等多个方法
 */
using ShkSimulation.core.exceptions;
using ShkSimulation.core.factory;
using ShkSimulation.core.template;
using System.Collections.Generic;
using System.Linq;
using ShkSimulation.carsharing;
using ShkSimulation.core.dao.input.loader;
using ShkSimulation.core.dao.statistic;
using ShkSimulation.core.template.agency;
using ShkSimulation.core.template.customer;
using ShkSimulation.carsharing.impl.create;
using ShkSimulation.carsharing.impl.model;

namespace ShkSimulation.carsharing.impl.elements {

    public class QueueNetwork : AbstractNetwork, DataReporter, CloneableNetwork {

        public string Uniquekey => UniqueId.ToString();
        private Dictionary<int, Station> stationDictionaryData;
        private Dictionary<int, Road> roadDictionaryData;
        
        public IReadOnlyDictionary<int, Station> Stations {
            get {
                List<Agency> stations =
                    NetworkInput?.ClassifiedAgencies?.GetValueOrDefault(CarsharingConfig.StationResourceKey);
                if (stations == null || stations.Count == 0) {
                    return null;
                }
                if (stationDictionaryData == null) {
                    stationDictionaryData = stations.ToDictionary(each => each.UniqueId, each => (Station)each);
                }
                return stationDictionaryData;
            }
        }
        public IReadOnlyDictionary<int, Road> Roads {
            get {
                List<Agency> roads =
                    NetworkInput?.ClassifiedAgencies?.GetValueOrDefault(CarsharingConfig.RoadResourceKey);
                if (roads == null || roads.Count == 0) {
                    return null;
                }
                if (roadDictionaryData == null) {
                    roadDictionaryData = roads.ToDictionary(each => each.UniqueId, each => (Road)each);
                }
                return roadDictionaryData;
            }
        }
        public IReadOnlyDictionary<int, Agency> AllAgencies => Agencies;

        public Dictionary<int, RoadServiceRateHelper> RoadServiceRateHelpers;

        public bool useNavigate;

        public bool UseNavigate => useNavigate;
        
        private QueueNetwork(int id,
            NetworkInputData inputData, 
            NetworkResultCollector resultCollector, 
            DemandManager demandManager, 
            CreateFactoriesFunc factoriesFunc, 
            int seed) 
                : base(id, inputData, resultCollector, demandManager, factoriesFunc, seed) {
            AfterAgenciesCreated += AgenciesCreated;
        }

        private void AgenciesCreated(NetworkInputData networkInputData, Dictionary<string, List<Agency>> dictionary) {
            List<Dispatcher> dispatchers = new List<Dispatcher>();
            List<Vehicle> vehicles = new List<Vehicle>();
            foreach (var station in Stations.Values) {
                dispatchers.AddRange(station.Dispatchers);
                vehicles.AddRange(station.Vehicles.Keys);
            }
            Dispatchers = dispatchers;
            Vehicles = vehicles;
        }

        public IReadOnlyList<Dispatcher> Dispatchers { get; private set; }
        public IReadOnlyList<Vehicle> Vehicles { get; private set; }

        public static QueueNetwork GenerateNetwork(NetworkInputData inputData, 
            NetworkResultCollector resultCollector, 
            DemandManager demandManager = null,
            CreateFactoriesFunc factoriesFunc = null, 
            int id = -1, int seed = 0) {

            if (inputData == null) {
                throw new SimulationInitException("NetworkInput 不能为空");
            }
            if (resultCollector == null) {
                throw new SimulationInitException("NetworkResultCollector 不能为空");
            }
            if (demandManager == null) {
                logger.Warn("创建默认需求管理器");
                demandManager = new DefaultDemandManager(CarsharingConfig.DemandResourceKey);
            }
            if (factoriesFunc == null) {
                logger.Warn("创建默认车站和道路工厂");
                factoriesFunc = FactoriesCreateFunction;
            }            
            return new QueueNetwork(id, inputData, resultCollector, demandManager, factoriesFunc, seed);
        }

        public static QueueNetwork GenerateNetwork(string configPath, 
            NetworkInputData inputData = null, 
            NetworkResultCollector resultCollector = null, 
            DemandManager demandManager = null,
            CreateFactoriesFunc factoriesFunc = null, 
            int id = -1, int seed = 0) {
            
            logger.Warn("创建默认路网输入即路网环境:{Path}", configPath);
            
            if (resultCollector == null) {
                logger.Warn("创建默认路网输出采集器");
                resultCollector = new NetworkResultHolder();
            }
            return GenerateNetwork(
                new NetworkEnvironment(configPath, new ExcelResourceLoader()),
                resultCollector,
                demandManager,
                factoriesFunc,seed);
        }

        public CloneableNetwork CloneOrCreate(int id, string name,
            NetworkInputData inputData = null,
            NetworkResultCollector resultCollector = null,
            DemandManager manager = null, int seed = 0) {
            inputData = inputData ?? NetworkInput.Clone();
            resultCollector = resultCollector ?? ResultCollector.Clone();
            manager = manager ?? DemandManager.Clone();
            return GenerateNetwork(inputData, resultCollector, manager, FactoriesCreateFunction, id, seed);
        }
        
        private Dictionary<string, double> reportRelatedDoubleData = new Dictionary<string, double>();

        /**
        * @description: DataReport
        */
        public DataReportInfo GetReportInfo() {
            reportRelatedDoubleData["开始时刻"] = NetworkStartTime.Ticks;
            reportRelatedDoubleData["当前时刻"] = ClockTime.Ticks;
            reportRelatedDoubleData["车站数"] = Stations.Count;
            reportRelatedDoubleData["道路数"] = Roads.Count;
            reportRelatedDoubleData["需求类别数"] = DemandManager.CustomerTemplate.Count;
            reportRelatedDoubleData["调度员数"] = Dispatchers.Count;
            reportRelatedDoubleData["车辆数"] = Vehicles.Count;
            reportRelatedDoubleData["总运行时长"] = (ClockTime - NetworkStartTime).TotalHours;
            return DataReportInfo.Create(UniqueId.ToString(), ClockTime, null, reportRelatedDoubleData);
        }
        
                
        protected static List<AgencyFactory> FactoriesCreateFunction(NetworkInputData networkInput) {
            AgencyFactory station = DefaultStationFactory(networkInput);
            AgencyFactory road = DefaultRoadFactory(networkInput);
            return new List<AgencyFactory>() {
                station, road
            };
        }


        public static AgencyFactory DefaultStationFactory(NetworkInputData environment) {
            AgencyFactory result = FactoryProvider.CreateFactory<StationFactory>(environment, CarsharingConfig.StationResourceKey);
            logger.Warn($"创建车站工厂 {result.GetType().FullName}");
            return result;
        }

        public static AgencyFactory DefaultRoadFactory(NetworkInputData environment) {
            AgencyFactory  result = FactoryProvider.CreateFactory<RoadFactory>(environment, CarsharingConfig.RoadResourceKey);
            logger.Warn($"创建道路工厂 {result.GetType().FullName}");
            return result;
        }
        
    }
}
